package drep;



import drep.ClientConnection;
import drep.ControlDrep;
import drep.ErrorHandler;
import drep.Promtp;
import drep.ServerConnection;
import java.io.File;

/**
 * Universidad Simón Bolívar
 * Curso de Redes I - Taller
 * Profesor: Ricardo Gonzalez
 * Trimestre Enero-Marzo 2011
 *
 * Proyecto 2 RD
 * Se desea implementar un sistema de repositorios de archivos, que llamaremos
 * Repositorios Distribuidos o RD, estos repositorios estarán constituidos por
 * tres tipos de componentes diferentes: uno de ellos será un programa que
 * llamaremos drep que se encargará de recibir, almacenar y entregar archivos
 * que sea subidos o solicitados por otros programas, los componentes dcli
 * serán programas que enviarán o solicitarán archivos a los programas drep del
 * sistema, en función de los requerimientos de los usuarios con los que
 * interactúan en su pantalla. Pueden existir varias instancias de programas
 * drep y de programas dcli en el sistema, pero debe existir una única instancia
 * del programa dmon, este último componente se encargará de llevar una serie de
 * datos de las operaciones que los programas dcli realizan en todos los
 * programas drep del sistema.
 *
 * Programa drep
 * Es un programa que tendrá un directorio en el que se almacenarán una serie de
 * archivos que los clientes puedan enviarle, adicionalmente debe poder responder
 * a informaciones sobre estos archivos como un listado de los archivos presentes,
 * y cuál es su longitud en bytes, de igual forma debe entregar el contenido
 * de uno de estos archivos, si algún cliente así se lo solicita.
 * Cada operación que realice en un drep debe ser notificada al único dmon del
 * sistema, para que este pueda generar datos globales del sistema.
 * Los datos del sistema podrán ser consultados por los dcli a través de los
 * programas drep, quienes a su vez pedirán la información al programa dmon.
 *
 * La sintaxis de la llamada a este programa será la siguiente:
 * drep -c <puerto local clientes> -h <host de dmon> -p <puerto dmon>
 *      -d <rdirectorio>
 *
 * @author Grupo 9
 * @author Richard Simoes Ferreira
 * @author Ricardo Tocco
 *
 * @version 1.0
 */
public class Main {

    /**
     * Función para capturar y verificar los parámetro introdcidos por el
     * usuario.
     *
     * @param args  lista de los parámetros de entrada
     * @return      Un apuntador a la estructura de control ControlDrep
     *              que agrupa toda la información necesaria para la correcta
     *              ejecución de los programas drep.
     */
    private static ControlDrep capturarParametros(String[] args){

        ErrorHandler errorH = new ErrorHandler();
        
        //Defaults
        int puertoLocal = 16000;
        int puertoDmon = 16000;
        String serverDmon = null;
        String rdirectorio = null;
        boolean flag_puerto_dmon = false;
        boolean flag_puerto_dcli = false;
        boolean flag_host = false;
        boolean flag_dir = false;

        ControlDrep control;


        if (args.length != 8) {
            errorH.argumentosInvalidos();

        } else {

            for(int i = 0; i < args.length; i++){
                if(args[i].equals("-c")){
                    if (!flag_puerto_dcli) {
                        puertoLocal = Integer.valueOf(args[++i]);

                        if (puertoLocal <= 1024 && puertoLocal >= 65535)
                            errorH.puertoInvalido(puertoLocal);
                        else flag_puerto_dcli = true;
                        
                    } else {
                        errorH.redifinicionArgumento("puerto clientes (-c)");
                    }
                } else if(args[i].equals("-h")){
                    if (!flag_host) {
                        serverDmon = args[++i];
                        flag_host = true;
                    } else {
                        errorH.redifinicionArgumento("host dmon (-h)");
                    }
                } else if (args[i].equals("-p")) {
                    if (!flag_puerto_dmon) {
                        puertoDmon = Integer.valueOf(args[++i]);

                        if (puertoDmon <= 1024 && puertoDmon >= 65535)
                            errorH.puertoInvalido(puertoDmon);
                        else flag_puerto_dmon = true;
                    } else {
                        errorH.redifinicionArgumento("puerto dmon (-p)");
                    }
                } else if (args[i].equals("-d")){
                     if (!flag_dir) {
                        rdirectorio = args[++i];
                        File verificarLdir = new File(rdirectorio);
                        if (!verificarLdir.isDirectory()){
                            errorH.directorioNoExiste();
                        } else {
                            if (!rdirectorio.endsWith("/")) rdirectorio += "/";
                            flag_dir = true;
                        }
                    } else {
                        errorH.redifinicionArgumento("rdirectorio (-d)");
                    }
                }

            }

            if(!(flag_puerto_dmon && flag_puerto_dcli && flag_host && flag_dir))
                errorH.argumentosInvalidos();
        }

        control = new ControlDrep(puertoLocal,serverDmon,puertoDmon,rdirectorio);
        return control;
    }

    /**
     * Función Principal para el programa dmon.
     *
     * @param args  lista de los parámetros de entrada
     * @return      0 si la ejecución es exitosa o cualquier otro valor en
     *              caso de error.
     */
    public static void main(String[] args) {
        ControlDrep control;
        ServerConnection server;
        ClientConnection clienteDmon;
        Promtp promtp;
        

        control = capturarParametros(args);

        server = new ServerConnection(control.getPuertoDcli(),control);
        clienteDmon = new ClientConnection(control.getPuertoDmon(),control.getServidorDmon());
        promtp = new Promtp(control);
        control.setClientDmon(clienteDmon);

        server.start();
        clienteDmon.Connect();
        promtp.run();

        server.terminar();
        clienteDmon.Disconnect();
        System.exit(0);


    }

}
